// 定义消息协议类型
interface UploadMessage {
  type: "progress" | "chunk-success" | "chunk-error" | "upload-complete";
  index?: number;
  progress?: number;
  hash?: string;
  error?: Error;
}

interface ChunkData {
  index: number;
  totalChunks: number;
  fileName: string;
  chunk: ArrayBuffer;
}

export default class FileUploader {
  private file: File;
  private chunkSize: number;
  private totalChunks: number;
  private currentChunk: number;
  private worker: Worker | null;
  private isPaused: boolean;
  private retryCount: number;

  constructor(file: File, chunkSize: number = 10 * 1024 * 1024) {
    this.file = file;
    this.chunkSize = chunkSize;
    this.totalChunks = Math.ceil(file.size / chunkSize);
    this.currentChunk = 0;
    this.worker = null;
    this.isPaused = false;
    this.retryCount = 0;
  }

  public start(): void {
    this.worker = new Worker(new URL("./worker.ts", import.meta.url));
    this.setupWorkerCommunication();
    this.uploadNextChunk();
  }

  private setupWorkerCommunication(): void {
    if (!this.worker) return;
    console.log(this.worker, "this.worker");

    this.worker.onmessage = (e: MessageEvent<UploadMessage>) => {
      switch (e.data.type) {
        case "progress":
          this.handleProgress(e.data.progress!);
          break;
        case "chunk-success":
          this.handleChunkSuccess(e.data.index!);
          break;
        case "chunk-error":
          this.handleError(e.data.index!, e.data.error!);
          break;
        case "upload-complete":
          this.handleComplete();
          break;
      }
    };
  }

  private uploadNextChunk(): void {
    if (this.isPaused || this.currentChunk >= this.totalChunks) return;

    const start = this.currentChunk * this.chunkSize;
    const end = Math.min(start + this.chunkSize, this.file.size);
    const chunk = this.file.slice(start, end);

    if (!this.worker) return;

    // 使用 Transferable Objects 优化内存
    this.worker.postMessage(
      {
        action: "upload-chunk",
        payload: {
          index: this.currentChunk,
          totalChunks: this.totalChunks,
          fileName: this.file.name,
          chunk,
        },
      },
      [chunk] // 传输 ArrayBuffer
    );
  }

  // 以下为事件处理方法
  private handleProgress(progress: number): void {
    // 更新UI逻辑
    console.log(`Progress: ${progress}%`);
  }

  private handleChunkSuccess(index: number): void {
    this.currentChunk = index + 1;
    this.uploadNextChunk();
  }

  private handleError(index: number, error: Error): void {
    this.retryCount++;
    if (this.retryCount < 3) {
      setTimeout(() => this.uploadNextChunk(), 2000);
    } else {
      this.terminateWorker();
      throw new Error(`Upload failed after 3 retries: ${error.message}`);
    }
  }

  private handleComplete(): void {
    this.terminateWorker();
    console.log("Upload complete");
  }

  public pause(): void {
    this.isPaused = true;
    this.terminateWorker();
  }

  public resume(): void {
    this.isPaused = false;
    this.uploadNextChunk();
  }

  private terminateWorker(): void {
    if (this.worker) {
      this.worker.terminate();
      this.worker = null;
    }
  }
}
